// 引入uuid
const {
    v4: uuidv4
} = require('uuid');

// 初始化房间和用户
let connectedUsers = [];
let rooms = [];

const socketFun = server => {
    // 将socket.io在次服务器上挂载
    const io = require('socket.io')(server, {
        cors: {
            origin: '*',
            methods: ['GET', 'POST'],
        }
    })
    io.on('connection', (socket) => {
        socket.on('createRoom', (data) => {
            createRoom(socket, data);
        })

        socket.on('joinRoom', data => {
            joinRoom(io, socket, data)
        })

        // 断开连接，名称固定
        socket.on('disconnect', data => {
            leaveRoom(io, socket)
        })

        socket.on('conn-signal', data => {
            signaling(io,data, socket)
        })

        socket.on('conn-init',data => {
            initConnection(io,data,socket)
        })
    })
}

// 创建房间的逻辑
const createRoom = (socket, data) => {
    // 获取创建人姓名
    const user = data.meettingUserName;
    const roomId = uuidv4(); // uuidv4返回一个随机值作为房间号

    // 创建新用户（进入会议的人）
    const newUser = {
        user,
        id: uuidv4(),
        roomId,
        socketId: socket.id
    }

    // 将用户加入到已连接数组种
    connectedUsers = [...connectedUsers, newUser]

    // 创建新房间
    const newRoom = {
        id: roomId,
        connectedUsers
    }

    // 新用户加入会议房间
    socket.join(roomId);

    // 将房间信息存入数组
    rooms = [...rooms, newRoom]

    // 响应客户端roomId
    socket.emit('roomId', {
        roomId
    })

    // 发送通知新用户加入房间
    socket.emit('roomUpdate', {
        connectedUsers: newRoom.connectedUsers
    })
}

// 加入房间的逻辑
const joinRoom = (io, socket, data) => { 
    const {
        roomId,
        meettingUserName: user
    } = data;
    // 创建该用户的信息
    const newUser = {
        id: uuidv4(),
        user,
        roomId,
        socketId: socket.id
    }

    // 判断roomId是否是已有的Id
    const room = rooms.find(r => r.id === roomId)
    if (room) {
        room.connectedUsers = [...room.connectedUsers, newUser]
    }

    // 加入房间
    socket.join(roomId)

    // 将用户加入到已连接数组中
    connectedUsers = [...connectedUsers, newUser]

    // 遍历数组，向其他用户发送webRTC对等连接申请
    room.connectedUsers.forEach(cu => {
        // 排除向自己发送webRTC申请
        if (cu.socketId !== socket.id) {
            const param = {
                connectUserSocketId: socket.id
            };

            io.to(cu.socketId).emit('rtcApply', param);
        }
    });

    // 广播通知所有房间内用户有新用户加入
    io.to(roomId).emit('roomUpdate', {
        connectedUsers: room.connectedUsers
    })
}

// 用户离开房间的逻辑
const leaveRoom = (io, socket) => {
    // 查询离开人员的信息
    const user = connectedUsers.find(user => user.socketId === socket.id)

    if (user) {
        // 删除用户,先找到房间
        const room = rooms.find(r => r.id === user.roomId);

        if (room) {
            // 将该用户从房间里删除
            room.connectedUsers = room.connectedUsers.filter(u => u.socketId !== socket.id)
        }

        // 离开房间
        socket.leave(user.roomId)

        // 会议房间无人存在时则删除房间，否则广播通知所有房间内用户有用户离开
        if (room.connectedUsers.length > 0) {
            // 用户断开webRTC连接
            io.to(room.id).emit('user-leave',{
                socketId:socket.id
            })

            // 发送通知告知有用户离开并更新房间
            io.to(room.id).emit('roomUpdate', {
                connectedUsers: room.connectedUsers
            })
        } else {
            rooms = rooms.filter(r => r.id !== room.id)
        }

    }
}

// 交换信令
const signaling = (io,data, socket) => {
    const {
        connectUserSocketId,signal
    } = data

    const signalingData = {signal,connectUserSocketId:socket.id}

    io.to(connectUserSocketId).emit('conn-signal',signalingData)
}

// 初始化对等连接
const initConnection = (io,data,socket) => {
    const {connectUserSocketId} = data;

    const initData = {
        connectUserSocketId: socket.id
    }

    io.to(connectUserSocketId).emit('conn-init',initData)
}

// 获取rooms和connectedUsers数据，如果在其他文件中直接require会导致，本文件数据变化时其他文件数据不变
const getRooms = () => {
    return rooms;
}

const getConnectedUsers = () => {
    return connectedUsers;
}
module.exports = {getRooms,getConnectedUsers,socketFun}